﻿﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using CrossesGrav.WorkClasses;

namespace CrossesGrav.GameLogic
{
    class AI : Player
    {
        EventArgs e = new EventArgs();

        int decreeser = 1;

        Random ran = new Random();
        Data[] VarsA = new Data[0];
        Data[] VarsB = new Data[0];
        float delta = 0.1f;

        public override void Move(int z) //обработка хода
        {

            ////////////////////
            // Form1.TestForm.Controls[0].Text = ""; // код между такими комментариями - вспомогательный. Он НЕ задействован в работе самой проги и в 95% случаев может быть безболезненно удален. Самые страшные последствия после этого - возможные ошибки в работе таких же вспомогательных блоков.
            // Game.logs_X.Clear();
            // Game.logs_O.Clear();
            ///////////////////
            if ((!Game.GameOver)&&(z>0))
            {
                u = z;
                Array.Resize(ref VarsA, Game.AvalibleCells.Count);
                Array.Resize(ref VarsB, Game.AvalibleCells.Count);
                // Сделать конструктор клетки, который все это сам реализует
                for (int i = 0; i < Game.AvalibleCells.Count; i++)
                {
                    VarsA[i].WCells = new Cell();
                    VarsA[i].Counts = new List<float>();
                    VarsA[i].FreeCells = new List<int>();
                    VarsA[i].Windws = new List<bool>();
                    VarsA[i].Nearly = new List<bool>();

                    VarsB[i].WCells = new Cell();
                    VarsB[i].Counts = new List<float>();
                    VarsB[i].FreeCells = new List<int>();
                    VarsB[i].Windws = new List<bool>();
                    VarsB[i].Nearly = new List<bool>();

                }
                Watcher(Game.AvalibleCells);

            }
           // else Program.f.pictureBox6_Click(new object(), new EventArgs());
        }
        public void Watcher(List<Cell> a_Cells)
        {
            Data[] temp;
            bool tmp_side;

            for (int q = 0; q < 2; q++)
            {
                if (q == 0)
                {
                    temp = VarsA;
                    tmp_side = this.side;
                }
                else
                {
                    temp = VarsB;
                    tmp_side = !this.side;
                }
                for (int i = 0; i < a_Cells.Count; i++)
                {
                    temp[i].WCells.stat.Cross = tmp_side;
                    temp[i].WCells.stat.Circle = !tmp_side;
                    temp[i].WCells.SideList = a_Cells[i].SideList;
                    temp[i].WCells.Number = a_Cells[i].Number;
                    SubWatcher(temp[i]);
                }
            }
            Analyzer(VarsA, VarsB);
        }

        private void SubWatcher(Data t) // Анализ ситуации "от лица" клетки - осмотр соседей, поиск родственных/пустых клеток, окон между ними. Сердце AI.
        { // То, что происходит ниже, описано в сопроводительном тексте.
            Cell WatchTo = t.WCells;
            List<bool> wasmodif = new List<bool>();
            //float delta = (0.1f);
           // bool err = false;
            ///////////
           // bool tempo = false;
           // string log = "";
            ///////////

            for (int z = 0; z < t.WCells.SideList.Count; z++)
            {
                t.Counts.Add(0);
                t.FreeCells.Add(0);
                t.Windws.Add(false);
                t.Nearly.Add(false);
               // err = false;

                while (true)
                {
                    try
                    {
                        if ((CompareStat(WatchTo.SideList[z], WatchTo)) && (WatchTo.stat.Free != true)) //Вывинтить в отдельный метод
                        {
                            t.Counts[z]++;
                            ////////////
                           // log += "клетка N " + WatchTo.SideList[z].Number.ToString() + " совпала с " + WatchTo.Number.ToString() + (char)13 + (char)10;
                            //////////////
                            if (!t.Windws[z])
                                t.Nearly[z] = true;

                            WatchTo = WatchTo.SideList[z];


                            //////////// блоки такого вида "log+=" и т.д. - нужны для обеспечения логгирования. Собирают отчет о проделках алгоритма в понятной форме. После чего все можно легко читать как текст.
                           // log += "обзор из клетки N" + WatchTo.Number.ToString() + (char)13 + (char)10;
                            ///////////На данный момент клетки, для которых ведется лог указываются в начальной менюшке. Сегодня перекручу логгер, чтобы не надо было ничего выбирать, а лог открывался в новом окне для каждой клетки, по которой шелкнули ПКМ.
                        }
                        else
                        {
                            ///////////
                            //log += "клетка N " + WatchTo.SideList[z].Number.ToString() + " не совпала с " + WatchTo.Number.ToString() + " или не свободна" + (char)13 + (char)10;
                            //////////
                            {
                                if ((WatchTo.SideList[z].stat.Free == true) && (WatchTo.SideList[z].stat.Acessibility == true))
                                {
                                    t.FreeCells[z]++;
                                    /////////////////
                                   // log += "клетка N " + WatchTo.SideList[z].Number.ToString() + " оказалась свободна" + (char)13 + (char)10;
                                    ///////////////////

                                    WatchTo = WatchTo.SideList[z];

                                    if (!t.Windws[z])
                                    {
                                        t.Windws[z] = true;
                                       // tempo = true;
                                       // log += "обнаружено окно" + (char)13 + (char)10;
                                        ///////////////
                                    }////////////
                                    //log += "обзор из клетки N" + WatchTo.Number.ToString() + (char)13 + (char)10;
                                    /////////////////////


                                }
                                else
                                    if ((CompareStat(WatchTo.SideList[z], t.WCells)))
                                    {
                                        t.Counts[z]++;
                                        /////////////////
                                        //log += "клетка N " + WatchTo.SideList[z].Number.ToString() + " совпала с оригиналом" + (char)13 + (char)10;
                                        ///////////////////
                                        WatchTo = WatchTo.SideList[z];
                                        /////////////////////
                                        //log += "обзор из клетки N" + WatchTo.Number.ToString() + (char)13 + (char)10;
                                        /////////////////////

                                    }
                                    else
                                        if ((z == 7) && (t.FreeCells[z] <= Game.forWin - 1))
                                        {
                                            t.FreeCells[z]++;
                                            WatchTo = WatchTo.SideList[z];
                                        }
                                        else
                                        {
                                            WatchTo = t.WCells;
                                            ////////////
                                            //log += "обзор из клетки N" + WatchTo.Number.ToString() + (char)13 + (char)10;
                                            /////////////////////
                                            break;
                                        }
                            }
                        }
                    }
                    catch
                    {
                        WatchTo = t.WCells;
                        //log += "ошибка обзора, возврат в N" + WatchTo.Number.ToString() + (char)13 + (char)10;
                       // err = true;
                        break;
                    }
                }
            }
            corrector(t);
           /* if (t.WCells.stat.Cross)
                Game.logs_X.Add(t.WCells.Number, log + (char)13 + (char)10 + Lib.Cell_IO_Checker(t));
            else
                Game.logs_O.Add(t.WCells.Number, log + (char)13 + (char)10 + Lib.Cell_IO_Checker(t));
            */
        }

        private void corrector(Data t) // Корректировщик индексов клеток. 
        {
            for (int z = 0; z < t.Counts.Count; z++)
            {
                if ((t.Windws[z]) && (t.Counts[z]) >= 1)
                {
                    t.Counts[z] -= delta;
                }

                if ((z != 3) && (!t.Windws[z]) && (t.Counts[z]) > 1)
                {
                    t.Counts[z] += delta;
                }

                if ((t.Nearly[z])&&(z!=3))
                {
                    t.Counts[z] += delta;
                }

            }
        }

        private void Analyzer(Data[] my, Data[] opp)
        {
            ArrDictionary<int, float> arrd_temp;
            Data[] pl_temp;
            ArrDictionary<int, float> arrd_M = new ArrDictionary<int, float>();
            ArrDictionary<int, float> arrd_O = new ArrDictionary<int, float>();
            List<float> string_temp = new List<float>();
            
            for (int t = 0; t < 2; t++)
            {
                if (t == 0)
                {
                    pl_temp = my;
                    arrd_temp = arrd_M;
                }
                else
                {
                    pl_temp = opp;
                    arrd_temp = arrd_O;
                }
                for (int i = 0; i < my.Length; i++)
                {
                    for (int j = 0; j < 3; j++)
                    {
                        float tmp1 = (pl_temp[i].FreeCells[j] + pl_temp[i].FreeCells[j + 4] + pl_temp[i].Counts[j] + pl_temp[i].Counts[j + 4] + delta);
                        float tmp2 =  (Game.forWin - decreeser);
                        if (tmp1 >= tmp2)
                        {
                            string_temp.Add(Calc(pl_temp[i].Counts[j] + pl_temp[i].Counts[j + 4]));
                        }
                    }
                    if ((pl_temp[i].Counts[3] + pl_temp[i].FreeCells[7] >= Game.forWin - decreeser))
                    {
                        string_temp.Add(Calc(pl_temp[i].Counts[3] + pl_temp[i].Counts[7]));
                    }
                    arrd_temp.Add(my[i].WCells.Number, Calc(string_temp));
                    string_temp.Clear();
                }
            }
            Brain(arrd_M, arrd_O);
        }

        private void Analyzer(ArrDictionary<int, float> work) //***************сортировка по возрастанию********************
        {
            for (int i = 0; i < work.Count; i++)
            {
                for (int j = 0; j < work.Count; j++)
                    if (work.GetData(i).value > work.GetData(j).value)
                    {
                        work.Replace(i, j);
                        j--;
                    }
            }

            //Дальше нужно индексировать массив коэффицентов
            ArrDictionary<float, List<int>> index_array = new ArrDictionary<float, List<int>>();
            for (int i = 0; i < work.Count; i++)
            {
                if (index_array.FindIn(work.GetData(i).key) < 0)
                {
                    //index_array.Add(work.GetData(i).key, ты все же подумай над тем, как собрать индексатор корректный....
                }
            }

        }

        private float Calc(float line)
        {
            return ((float)line / (Game.forWin - 1)) * 100;
        }

        private float Calc(List<float> K)
        {
            float temp = 0;

            for (int i = 0; i < K.Count; i++)
            {
                if (K[i] > temp) temp = K[i];
            }
            return temp;

        }

        private ArrDictionary<int, float> test(ArrDictionary<int, float> tst) //*******************************
        {
            return null;
        }

        private void Brain(ArrDictionary<int, float> my1, ArrDictionary<int, float> opp1)
        {
            ////////////////////////////////
           // for (int i = 0; i < my1.Count; i++)            
            {
               // Game.tmpInd[my1.GetData(i).key].Text = Convert.ToString(my1.GetData(i).value);
            }
            ////////////////////////////////

            my1.downSort_val();
            opp1.downSort_val();
            MouseEventArgs mea = new MouseEventArgs(MouseButtons.Left,1,1,1,1);
            ArrDictionary<int, float> tmp;

            if (my1.GetData(0).value >= opp1.GetData(0).value)
            {
                tmp = my1;
            }
            else tmp = opp1;

            if (my1.GetData(0).value == 0)
            {
                Game.AvalibleCells[ran.Next(0, Game.AvalibleCells.Count)].Box_Click(this, mea);
                this.VarsA = null;
                this.VarsB = null;
            }
            else
                for (int i = 0; i < Game.AvalibleCells.Count; i++)
                {
                        if (Game.AvalibleCells[i].Number ==tmp.GetData(0).key)
                        {
                            Game.AvalibleCells[i].Box_Click(this, mea);
                            this.VarsA = null;
                            this.VarsB = null;

                            break;
                        }
                }
        }

    }

}